﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using TransitionEffects;

namespace SharpSoft.WPF
{
    public static class VisualHelper
    {
        /// <summary>
        /// 捕获UI元素的快照
        /// </summary>
        /// <param name="visual"></param>
        /// <param name="CaptureType">快照方式</param>
        /// <returns></returns>
        public static RenderTargetBitmap Capture(this UIElement visual, CaptureType captureType = CaptureType.BitmapCacheBrush)
        {
            DrawingVisual dv = null;
            if (captureType != CaptureType.Direct)
            {
                dv = new DrawingVisual();
                using (DrawingContext ctx = dv.RenderOpen())
                {
                    //这里使用BitmapCacheBrush理论上要比VisualBrush快不少，未实际测试所耗时间。
                    //但是BitmapCacheBrush可能不支持UI元素的Clip、OpacityMask等特性，未实际测试。
                    visual.CacheMode = new BitmapCache() { EnableClearType = true };
                    Brush vb;
                    if (captureType == CaptureType.BitmapCacheBrush)
                    {
                        vb = new BitmapCacheBrush(visual) { AutoLayoutContent = true, BitmapCache = new BitmapCache() { EnableClearType = true } };
                    }
                    else
                    {
                        vb = new VisualBrush(visual);
                    }
                    ctx.DrawRectangle(vb, null,
                        new Rect(new Point(0, 0), visual.RenderSize));
                }
            }
            RenderTargetBitmap bmp = new RenderTargetBitmap((int)visual.RenderSize.Width, (int)visual.RenderSize.Height, 96, 96, PixelFormats.Default);
            if (captureType == CaptureType.Direct)
            {
                bmp.Render(visual);
            }
            else
            {
                bmp.Render(dv);
            }

            bmp.Freeze();
            return bmp;
        }

        /// <summary>
        /// 查找指定类型的父级控件（返回第一个遇到的）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ui"></param>
        /// <returns></returns>
        public static T FindParent<T>(DependencyObject ui) where T : DependencyObject
        {
            if (ui == null)
            {
                return null;
            }
            DependencyObject parent = ui;
            do
            {
                parent = VisualTreeHelper.GetParent(parent);
            } while (parent != null && !(parent is T));
            return parent as T;
        }
        /// <summary>
        /// 查找指定类型的子集控件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="ui"></param>
        /// <returns></returns>
        public static T FindChild<T>(DependencyObject ui) where T : DependencyObject
        {
            var count = VisualTreeHelper.GetChildrenCount(ui);
            if (count > 0)
            {
                for (int i = 0; i < count; i++)
                {
                    var child = VisualTreeHelper.GetChild(ui, i);
                    if (child is T ct)
                    {
                        return ct;
                    }
                    else if (child != null)
                    {
                        var c = FindChild<T>(child);
                        if (c != null)
                        {
                            return c;
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// 递归检查控件是否有数据验证错误
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public static bool CheckHasDataError(this DependencyObject control)
        {
            var selferror = System.Windows.Controls.Validation.GetHasError(control);
            if (selferror)
            {
                return true;
            }
            var cc = VisualTreeHelper.GetChildrenCount(control);
            if (cc == 0)
            {
                return false;
            }
            for (int i = 0; i < cc; i++)
            {
                var child = VisualTreeHelper.GetChild(control, i);
                if (child != null)
                {
                    var childerror = CheckHasDataError(child);
                    if (childerror)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// <summary>
        /// 对指定控件下的所有子控件进行绑定验证并更新其数据源
        /// </summary>
        /// <param name="control"></param>
        public static void UpdateBindingSource(this DependencyObject control)
        {
            if (control is Control ui)
            {
                var fields = ui.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static| System.Reflection.BindingFlags.FlattenHierarchy);
                var dpt = typeof(DependencyProperty);
              
                foreach (var item in fields)
                {
                    if (item.FieldType == dpt)
                    {
                        var dp = item.GetValue(null) as DependencyProperty; 
                        var be = ui.GetBindingExpression(dp);
                        if (be != null)
                        {
                            be.UpdateSource();
                        }

                    }
                }

            }
            var cc = VisualTreeHelper.GetChildrenCount(control);
            if (cc == 0)
            {
                return;
            }
            for (int i = 0; i < cc; i++)
            {
                var child = VisualTreeHelper.GetChild(control, i);
                if (child != null)
                {
                    UpdateBindingSource(child);
                }
            }
        }

    }



    /// <summary>
    /// 定义捕获控件快照的方式
    /// </summary>
    public enum CaptureType
    {
        /// <summary>
        /// 直接捕获（效率最低）
        /// </summary>
        Direct,
        /// <summary>
        /// 使用位图缓存画刷<see cref="System.Windows.Media.BitmapCacheBrush"/>（速度最快）
        /// </summary>
        BitmapCacheBrush,
        /// <summary>
        /// 使用<see cref="System.Windows.Media.VisualBrush"/>
        /// </summary>
        VisualBrush
    }
}
